import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, ObjectId } from 'mongoose';
// import { CreatePhotosProfileDto } from './dto/create-photosProfile.dto';
import { PhotosProfile, PhotosProfileDocument } from './schemas/photosProfile.schema';
import * as dayjs from 'dayjs';
import { Photos, PhotosDocument } from './schemas/photos.schema';
import { HotListPhotosProfileDto } from './dto/hotList-photosProfile.dto';
import { User, UserDocument } from '@api/user/schemas/user.schema';
@Injectable()
export class PhotosProfileService {
    constructor(
        @InjectModel(User.name) private userModel: Model<UserDocument>,
        @InjectModel(PhotosProfile.name) private photosProfileModel: Model<PhotosProfileDocument>,
        @InjectModel(Photos.name) private photosModel: Model<PhotosDocument>
    ) {}

    async findOneOrCreate(photosId: string & ObjectId) {
        let res = await this.photosProfileModel.findOne({ photos: photosId }).exec();
        if (!res) {
            const photosItem = await this.photosModel.findById(photosId).exec();
            if (!photosItem) throw new BadRequestException('作品不存在！！');
            const entity = new this.photosProfileModel({
                photos: photosId,
                user: photosItem.user,
                lastVisit: new Date(),
            });
            res = await entity.save();
        }
        return res;
    }
    async clickItem(photosId: string & ObjectId) {
        const item = await this.findOneOrCreate(photosId);
        const newDate = new Date();
        const now = dayjs(newDate);
        item.totalVisit += 1;
        const sameDay = now.isSame(item.lastVisit, 'day');
        const sameWeek = now.isSame(item.lastVisit, 'week');
        const sameMonth = now.isSame(item.lastVisit, 'month');
        item.dayVisit = 1 + (sameDay ? item.dayVisit : 0);
        item.weekVisit = 1 + (sameWeek ? item.weekVisit : 0);
        item.monthVisit = 1 + (sameMonth ? item.monthVisit : 0);
        item.dayDown = sameDay ? item.dayDown : 0;
        item.weekDown = sameWeek ? item.weekDown : 0;
        item.monthDown = sameMonth ? item.monthDown : 0;
        item.lastVisit = newDate;
        return await item.save();
    }
    async downItem(photosId: string & ObjectId) {
        const item = await this.findOneOrCreate(photosId);
        const newDate = new Date();
        const now = dayjs(newDate);
        item.totalDown += 1;
        const sameDay = now.isSame(item.lastVisit, 'day');
        const sameWeek = now.isSame(item.lastVisit, 'week');
        const sameMonth = now.isSame(item.lastVisit, 'month');
        item.dayDown = 1 + (sameDay ? item.dayDown : 0);
        item.weekDown = 1 + (sameWeek ? item.weekDown : 0);
        item.monthDown = 1 + (sameMonth ? item.monthDown : 0);
        item.dayVisit = sameDay ? item.dayVisit : 0;
        item.weekVisit = sameWeek ? item.weekVisit : 0;
        item.monthVisit = sameMonth ? item.monthVisit : 0;
        item.lastVisit = newDate;
        return await item.save();
    }

    async findAll() {
        return await this.photosProfileModel.find().sort('-orderIndex').exec();
    }
    async hotList(dto: HotListPhotosProfileDto) {
        const { page = 0, psize = 20 } = dto.limit || {};
        const thisWeek = dayjs().startOf('week').toDate();
        const res = await this.photosProfileModel
            .find({ lastVisit: { $gte: thisWeek } })
            .populate([{ path: 'user', select: 'nickname avatar desc' }, { path: 'photos' }])
            .skip(page * psize)
            .limit(psize)
            .sort('-weekDown')
            // .sort('-createdAt')
            .exec();
        return res.map(it => {
            const item = it.toObject();
            return {
                ...item.photos,
                user: item.user,
                profile: { totalDown: item.totalDown },
            };
        });
    }
    // 发现列表
    async findList(dto: HotListPhotosProfileDto) {
        const { page = 0, psize = 20 } = dto.limit || {};

        const thisWeek = dayjs().startOf('week').toDate();

        const res = await this.photosProfileModel.aggregate([
            { $match: { lastVisit: { $gte: thisWeek } } },
            {
                $group: {
                    _id: '$user',
                    weekSum: { $sum: '$weekDown' },
                    totalSum: { $sum: '$totalDown' },
                },
            },
            { $sort: { weekSum: -1 } },
            { $skip: page * psize },
            { $limit: psize },
        ]);
        if (res.length === 0) {
            return [];
        }
        const [profileList, users] = await Promise.all([
            Promise.all(
                res.map(it =>
                    this.photosProfileModel
                        .find({ user: it._id, weekDown: { $ne: 0 } })
                        .populate({ path: 'photos' })
                        .limit(3)
                        .sort('-weekDown')
                        .exec()
                )
            ),
            this.userModel.find({ _id: { $in: res.map(it => it._id) } }, 'nickname avatar desc').exec(),
        ]);

        const result = res.map((it, index) => {
            const findUser = users.find(item => String(item._id) === String(it._id));
            return {
                ...it,
                profile: profileList[index],
                ...findUser.toObject(),
            };
        });
        return result;
    }
}
